Categories
Modern JavaScript

Best of Modern JavaScript — Function Names and Arrow Functions

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at function names and arrow functions in JavaScript.

Determine Whether a Function was Invoked via new

We can find out whether a function was invoked with new by using the new.target property.

For instance, we can write the following to let us stop the function from being called with new :

function foo() {
  if (new.target !== undefined) {
    throw new Error('cannot be called as constructor');
  }
  //...
}

If we call it with new foo() , we get the error ‘Uncaught Error: cannot be called as constructor’.

With ES5, we can check for the value of this :

function foo() {
  "use strict";
  if (this !== undefined) {
    throw new Error('cannot be called as constructor');
  }
  //...
}

If this is undefined in strict mode, then we know it’s not called with new .

Arrow Functions

Arrow functions are new kinds of functions introduced with ES6.

It solves the problem of bindings with this , arguments and other built-in objects.

Also, they can’t be used as constructors and they’re shorter.

This means they’re great for callbacks.

Traditional Functions are Bad Non-Method Functions

Traditional functions are bad non-method functions since they bind to their own value of this inside the function.

Therefore, the following example won’t work:

function Suffix(suffix) {
  this.suffix = suffix;
}

Suffix.prototype.addSuffix = function(arr) {
  'use strict';
  return arr.map(function(x) {
    return x + this.suffix;
  });
};

The callback is defined with a traditional function, so it has its own value of this .

Therefore, there’s no suffix property in the callback.

To fix this, we can assign the this outside to another value.

For instance, we can write:

function Suffix(suffix) {
  this.suffix = suffix;
}

Suffix.prototype.addSuffix = function(arr) {
  'use strict';
  var that = this;
  return arr.map(function(x) {
    return x + that.suffix;
  });
};

We assigned this outside the callback to that , so that we can use it in the callback.

We can also specify the value of this with the map method.

The value is passed into the 2nd argument:

function Suffix(suffix) {
  this.suffix = suffix;
}

Suffix.prototype.addSuffix = function(arr) {
  'use strict';
  return arr.map(function(x) {
    return x + this.suffix;
  }, this);
};

We pass this into the 2nd argument to set this in the callback to the Suffix constructor.

And we can also use bind(this) to return a new function with the this value we want:

function Suffix(suffix) {
  this.suffix = suffix;
}

Suffix.prototype.addSuffix = function(arr) {
  'use strict';
  return arr.map(function(x) {
    return x + this.suffix;
  }.bind(this));
};

With ES6, we don’t need to do any of this.

We just use arrow functions:

function Suffix(suffix) {
  this.suffix = suffix;
}

Suffix.prototype.addSuffix = function(arr) {
  return arr.map((x) => {
    return x + this.suffix;
  });
};

We replace our function with an arrow function so won’t have to worry about the value of this in the callback.

We can replace the constructor with the class syntax:

class Suffix {
  constructor(suffix) {
    this.suffix = suffix;
  }

  addSuffix(arr) {
    return arr.map((x) => {
      return x + this.suffix;
    });
  }
}

We put everything inside the class.

Conclusion

We can determine whether a function is called with new in various ways.

Also, arrow functions don’t bind to any special values like this inside it, so we can use them for callbacks easily.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *